Design Trade Offs:

 

 

Design Trade Off - Copying Not Allowed:

In each pseudoPOD class declaration I've included the constructor(), destructor(), and copy constructor() functions, and made them private, so that only the friendly enclosing class can create the pseudoPOD.  This prevents code outside the enclosing class from explicitly making copies of the pseudoPOD, and also blocks the compiler from implicitly making copies. 

Making a copy by first converting the pseudoPOD to a POD, and then making a copy of the POD, is still permitted, it is only the making of active copies that call the get() & set() functions that is prohibited. 

There are several possible ways of making active copies of an active member like a pseudoPOD, all of which have problems.

The simplest method would be to delete the explicit copy constructor() function, and make the destructor() function public, so the compiler's built-in copier would allocate memory for a duplicate of the pseudoPOD, then copy the contents of the original pseudoPOD byte by byte to the copy, and eventually destroy the copy using the destructor() and releasing the allocated memory.  The copy would have a *ep pointer to the enclosing class with the same value as the original, so would call the same get() & set() functions, and cause the same changes as calling the original.  This is counter-intuitive, in that coders expect that a copy of a POD will be independent, so that changing the copy will not change the original, nor vice-versa.

In addition, for arrays a simple copy would break the method of calculating the array index.  This depends on comparing the address in the "this" pointer of the array element being read or written to the address of element [0] of the array, but a copy of an element of the array would exist in memory allocated outside the original array, so would have a "this" address outside the range of the array, so would make it impossible to determine the index of the element being read or written.  I could add another word to each array element that would hold the index of the element, so that a simple copy would also have a copy of the index embedded in it, but that would increase memory consumption, already a problem since each and every array element has to have a *ep pointer to the enclosing class.

A different method would be to move the value of the pseudoPOD from the enclosing class to the nested class, so that the copy would have its own independent copy of the value, but then the get() & set() routines would make changes to the physical object they represent without recording that fact in the original copy of the pseudoPOD, which could cause trouble.  If, for example, a class represented a car, with one pseudoPOD member controlling the speed, and another controlling the motorized convertible top position, then:

1) some code could set the car.speed to 0 in the original,

2) then other code could set car.speed to 70 in the copy, which would make the get() and set() routines change the real car's speed to 70 while changing the speed value in the copy, but without changing the speed value in the original,

3) then still more code could, for safety's sake, check the car's speed in the original, and, finding it was safely at 0, change the pseudoPOD controlling the convertible top's position from closed & locked to open, causing the front edge of the top to unlatch, and the top to rotate from its closed position atop the passenger compartment to its open position, stowed in the trunk, with destructive rapidity.

Yet another possibility would be to denature the copy, so that changing it would not change the original, nor the real object controlled by the original, but that would make it truly identical to a POD, so we might as well make the copy a POD in the first place.  The compiler usually does this automatically, and where it doesn't we can prod it with a type cast, e.g.

printf ("fred.int3 = %i\n", (int)fred.int3);

 

Design Trade Off - Self-Assignment:

The pseudoPOD code doesn't check for self assignment, because it doesn't allocate or free memory or other resources, so doesn't have to worry about releasing a resource before it's been copied.  If, however, the coder allocates or releases resources in the get() & set() routines, then the coder should do so in a fashion that is self-assignment-safe and exception-safe, as described, for example, in Scott Meyers' book "Effective C++".